package com.woniu.adapter;

import com.woniu.inlet.web.fo.FixedInputBuyFo;
import com.woniu.inlet.web.fo.FixedInputBuyOrder;
import com.woniu.outlet.client.SendOrderMsgToPayFeign;
import com.woniu.outlet.client.mq.BuyRevocationPayMQ;
import com.woniu.outlet.mysql.dao.ProductBuyDao;
import com.woniu.outlet.mysql.po.PersonalFixedMySQL;
import com.woniu.outlet.mysql.po.ProductBuyMySQL;
import com.woniu.outlet.mysql.po.ProductBuyMySQLExample;
import com.woniu.service.domain.FixedOrCurrentBuyDto;
import com.woniu.service.domain.FundOrGoldBuyDto;
import com.woniu.service.domain.UpdateBuyDto;
import com.woniu.utils.DateUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.util.Arrays;
import java.util.List;

/**
 * 产品买入的适配层
 */
@Slf4j
@Component
@Transactional
public class ProductBuyAdapter {

    @Autowired
    private ProductBuyDao buyDao;

    @Autowired
    private PersonalIncomeAdapter personalIncomeAdapter;


    @Autowired
    private PersonalFixedAdapter fixedAdapter;

    @Autowired
    private FixedCurrentIncomeAdapter currentIncomeAdapter;

    @Autowired
    private SendOrderMsgToPayFeign sendOrderMsgToPayFeign;

    /**
     * 基金或者黄金非定投的买入
     *
     * @param dto
     */
    public void fundOrGoldBuy(FundOrGoldBuyDto dto) {
        addFundOrGoldOrder(dto);
    }

    /**
     * 基金或者黄金定投的买入
     *
     * @param dto
     * @return
     */
    public void fixedInputBuy(FixedInputBuyFo dto) {
        String[] s = dto.getFixedDate().split("/");
        String fixedType = s[0];
        String fixedDay = s[1];
        //判断定投类型
        if (fixedType.equals("week")) {
            //按周定投，判断今日与需求周几定投是否一致
            if (String.valueOf(DateUtil.getDayForWeek()).equals(fixedDay)) {
                //今日是周三与需求周三定投一致
                //存入个人定投表,状态为-1
                fixedAdapter.insert_1(dto, fixedType, fixedDay);
                log.debug("当前定投与今日week一致");
            } else {
                //不是当日定投，存入个人定投表,状态为0
                fixedAdapter.insert0(dto, fixedType, fixedDay);
            }
        } else {
            //按月定投，判断今日与需求几号定投是否一致
            if (String.valueOf(DateUtil.getDayForNumber()).equals(fixedDay)) {
                //今日是23号与需求23号定投一致
                //存入个人定投表,状态为-1
                fixedAdapter.insert_1(dto, fixedType, fixedDay);
                log.debug("当前定投与今日month一致");
            } else {
                //不是当日定投，存入个人定投表,状态为0
                fixedAdapter.insert0(dto, fixedType, fixedDay);
            }
        }

    }

    /**
     * 定期或活期理财的购买
     *
     * @param dto
     */
    public void fixedOrCurrentBuy(FixedOrCurrentBuyDto dto) {
        addFixedOrCurrentOrder(dto);
        log.debug("定期或活期理财生成订单");
        currentIncomeAdapter.insert(dto);
        log.debug("生成定期、活期产品收益单子");
    }

    /**
     * 生成基金和黄金订单信息
     *
     * @param dto
     */
    public int addFundOrGoldOrder(FundOrGoldBuyDto dto) {
        ProductBuyMySQL buyMySQL = new ProductBuyMySQL();
        BeanUtils.copyProperties(dto, buyMySQL);
        buyMySQL.setBuyFixed("n");
        buyMySQL.setFixedDate("0");
        buyMySQL.setBuyCost("0");
        buyMySQL.setBuyShare(0.0);
        buyMySQL.setRevocationTime(DateUtil.getSendBuyDate(buyMySQL.getBuyTime()));
        buyMySQL.setStatus(0);
        buyMySQL.setPayId(dto.getPayId());
        log.debug("生成基金和黄金订单信息");
        return buyDao.insertSelective(buyMySQL);
    }

    /**
     * 生成基金定投订单信息
     *
     * @param dto
     */
    public String addFixedInputOrder(PersonalFixedMySQL p) {
        ProductBuyMySQL buyMySQL = ProductBuyMySQL.builder()
                .userId(p.getUserId())
                .productType(p.getProductType())
                .codeId(p.getCodeId())
                .buyAmount(p.getFixedAmount())
                .buyCost("0")
                .buyShare(0.0)
                .buyTime(DateUtil.getBuyTime())
                .buyFixed(p.getId().toString())
                .fixedDate(p.getFixedType() + "/" + p.getFixedDay())
                .payId(0)
                .status(-4)
                .build();
        log.debug("生成基金定投订单信息");
        buyDao.insertSelective(buyMySQL);
        return buyMySQL.getId().toString();
    }

    /**
     * 生成定期和活期订单信息
     *
     * @param dto
     */
    public int addFixedOrCurrentOrder(FixedOrCurrentBuyDto dto) {
        ProductBuyMySQL buyMySQL = new ProductBuyMySQL();
        BeanUtils.copyProperties(dto, buyMySQL);
        buyMySQL.setBuyCost("0");
        buyMySQL.setBuyShare(0.0);
        buyMySQL.setBuyFixed("n");
        buyMySQL.setFixedDate("0");
        buyMySQL.setRevocationTime("0");
        buyMySQL.setStatus(-1);
        return buyDao.insertSelective(buyMySQL);
    }

    /**
     * 支付模块买入成功后修改订单状态
     *
     * @param dto
     */
    public void updateBuyStatus(UpdateBuyDto dto) {
        ProductBuyMySQL buyMySQL = ProductBuyMySQL.builder()
                .id(dto.getId())
                .buyCost(dto.getBuyCost())
                .buyShare(dto.getBuyShare())
                .status(-1)
                .build();
        buyDao.updateByPrimaryKeySelective(buyMySQL);
        //获取当前订单信息
        ProductBuyMySQL buy = buyDao.selectByPrimaryKey(dto.getId());
        //买入成功(相当于确认份额了)后，在个人收益表中创建个人收益信息
        Long incomeId = personalIncomeAdapter.insert(buy);
        log.debug("买入成功，存入收益表，开始计算收益");
    }


    /**
     * 得到符合条件的所有订单信息
     * 条件：  startTime < 日期 < endTime 且 typr=fund或者gold ,状态=0的->待买入
     *
     * @param startTime
     * @param endTime
     * @return
     */
    public List<ProductBuyMySQL> getAllTimeCondition(String startTime, String endTime) {
        ProductBuyMySQLExample example = new ProductBuyMySQLExample();
        String[] type={"fund","gold"};
        example.or()
                .andBuyTimeBetween(startTime, endTime)
                .andStatusEqualTo(0)
                .andBuyFixedEqualTo("n")
                .andProductTypeIn(Arrays.asList(type));
        return buyDao.selectByExample(example);
    }

    /**
     * 查询用户所有非删除的订单，即订单状态为 0 -1 -2 的
     *
     * @param userId
     * @return
     */
    public List<ProductBuyMySQL> findUserOrder(Long userId) {
        ProductBuyMySQLExample example = new ProductBuyMySQLExample();
        Integer[] status = {0, -1, -2};
        example.or()
                .andUserIdEqualTo(userId)
                .andStatusIn(Arrays.asList(status));
        example.setOrderByClause("buy_time desc");
        return buyDao.selectByExample(example);
    }

    /**
     * @param id 订单id
     */
    public void delById(Long id) {
        buyDao.deleteByPrimaryKey(id);
    }


    /**
     * 得到当前用户购买这只基金的明细
     * @param userId
     * @param codeId
     */
    public List<ProductBuyMySQL> getBuyDetails(Long userId, String codeId) {
        ProductBuyMySQLExample example=new ProductBuyMySQLExample();
        ProductBuyMySQLExample.Criteria criteria = example.createCriteria();
        criteria.andUserIdEqualTo(userId);
        criteria.andCodeIdEqualTo(codeId);
        Integer[] status = {0, -1, -2};
        criteria.andStatusIn(Arrays.asList(status));
        return buyDao.selectByExample(example);
    }

    /**
     * 撤销订单 订单状态，0:待买入(可以撤销订单)，-1:已买入，-2:已撤销订单，-3:删除订单
     * @param bId
     * @return
     */
    public String revocationOrder(String bId) {
        //得到撤销请求的小时
        int hour = DateUtil.getHour();
        //得到订单的撤销时间
        ProductBuyMySQL mySQL = buyDao.selectByPrimaryKey(Long.valueOf(bId));
        if(mySQL.getStatus()!=0){//不可撤销状态
            //不能撤销
            return "n";
        }
        String revocationTime = mySQL.getRevocationTime();
        //判断当前时间与撤销时间是否相等
        int i = DateUtil.getDays(revocationTime);
        if (i < 0) {
            //说明在撤销日期之前，可以撤销
            revocation(mySQL);
            return "y";
        }
        if (i == 0) { //说明是撤销当日
            //判断当前时间是否小于撤销时间的15点之前，小于就可以撤销，否则不能撤销
            if (hour < 15) {
                //可以撤销
                revocation(mySQL);
                return "y";
            }
        }
        //不能撤销
        return "n";
    }

    private void revocation(ProductBuyMySQL mySQL) {
        mySQL.setStatus(-2);
        buyDao.updateByPrimaryKey(mySQL);
        log.debug("【买入】订单撤销成功");
        sendOrderMsgToPayFeign.sendMessage(BuyRevocationPayMQ.EXCHANGE,BuyRevocationPayMQ.ROUTING_KEY,mySQL.getPayId().toString());
        log.debug("通知【支付模块订单撤销】成功");
    }

    /**
     * 定投产品的确认
     * @param fi
     */
    public void confirmFixedInputBuyOrder(FixedInputBuyOrder fi) {
        ProductBuyMySQL buyMySQL = buyDao.selectByPrimaryKey(Long.valueOf(fi.getId()));
        buyMySQL.setBuyFixed("y");
        buyMySQL.setRevocationTime(fi.getRevocationTime());
        buyMySQL.setPayId(fi.getPayId());
        buyMySQL.setStatus(0);
        buyDao.updateByPrimaryKey(buyMySQL);
    }

    public ProductBuyMySQL findOrderById(int buyId) {
        return buyDao.selectByPrimaryKey(Long.valueOf(buyId));
    }

    /**
     * 余额不足，删除已生成的定投买入订单
     * @param fixedInputBuyOrder
     */
    public void delFixedInputBuyOrder(FixedInputBuyOrder fixedInputBuyOrder) {
        ProductBuyMySQL mySQL = buyDao.selectByPrimaryKey(Long.valueOf(fixedInputBuyOrder.getId()));
        fixedAdapter.updateStatus_2(Long.valueOf(mySQL.getBuyFixed()));
        log.debug("fixedId={},进入14点的定投",mySQL.getBuyFixed());
        buyDao.deleteByPrimaryKey(Long.valueOf(fixedInputBuyOrder.getId()));
        log.debug("删除买入对应的买入订单");
    }
}
